{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 问题：re 里面 match() 和 search() 的区别\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "\n",
    "面试官想从这道题中考察面试人什么？\n",
    "re 是 Python 中的正则表达式操作模块，属于 Python 标准库的一部分。\n",
    "\n",
    "无论你是做后端、数据分析亦或是 Python 的其他相关职位，我想 re 模块都会是你 100% 会用到的。所以面试官肯定希望你掌握 re 的基本用法以及正则表达式的相关内容。\n",
    "\n",
    "在这个小节中我选了两个比较有代表性的问题，也是在面试中会经常被问到的，来帮助大家度过面试中有关 re 的关卡。\n",
    "\n",
    "答案\n",
    "match 只核对正则表达式是否匹配字符串的开头。\n",
    "\n",
    "re.match(\"匹配的正则表达式\", \"要匹配的字符串\")\n",
    "而 search 会扫描整个字符串和查找此正则匹配的任何位置。\n",
    "\n",
    "re.search(\"匹配的正则表达式\", \"要匹配的字符串\") # Search 函数的使用方法和 match 函数一致\n",
    "\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 拓展"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**什么是正则表达式（或称 RE、正则、正则表达式模式）？**\n",
    "\n",
    "一个正则表达式指定了一个字符串模式，我们可以用这个模式去匹配字符串。而 re 模块中的函数可以检查某个字符串是和给定的正则表达式匹配。\n",
    "\n",
    "在底层执行中，正则表达式模式会被编译成一系列字节码，然后由用 C 编写的匹配引擎执行。\n",
    "\n",
    "Tips： 以下的代码都是默认导入了 re 模块的。\n",
    "\n",
    "re.match 和 re.search\n",
    "先来看下题目中提到的这两个函数的具体使用：\n",
    "\n",
    ">>> print(re.match('super', 'superstition').span())\n",
    "(0, 5)\n",
    ">>> print(re.match('super', 'insuperable'))\n",
    "None\n",
    ">>> print(re.search('super', 'superstition').span())\n",
    "(0, 5)\n",
    ">>> print(re.search('super', 'insuperable').span())\n",
    "(2, 7)\n",
    "match 和 search 如果不能匹配成功的话，则返回 None。如果匹配成功，将返回一个匹配对象实例。实例包含匹配结果的相关的信息：起始和终结位置、匹配的子串以及其它。下面列出了匹配对象实例支持的一部分方法：\n",
    "\n",
    "方法\t描述\n",
    "group()\t返回正则匹配的字符串\n",
    "start()\t返回匹配的开始位置\n",
    "end()\t返回匹配的结束位置\n",
    "span()\t返回包含匹配 (start, end) 位置的元组\n",
    "匹配对象的 group 方法经常被用到，尤其当正则表达式较为复杂的时候，我们可能想过滤出一些有用的子组或重新组合子组，这个时候 group 方法就会闪亮登场。\n",
    "\n",
    ">>> res = re.match(r\"(\\w+) (\\w+)\", \"Isaac Newton, physicist\") # 匹配两个Unicode词语的字符\n",
    ">>> res.group() #\n",
    "'Isaac Newton'\n",
    ">>> res.group(1)\n",
    "'Isaac'\n",
    ">>> res.group(2)\n",
    "'Newton'\n",
    ">>> res.group(2, 1) # 返回一个元组\n",
    "('Newton', 'Isaac')\n",
    "当然 re 还包括其它的一些使用方法，下面我们一起来看看其中常用的两种，re.compile 和 re.sub。\n",
    "\n",
    "re.compile\n",
    "re.compile 将正则表达式字符串编译成一个正则对象，对于正则对象可以再使用 match，search 等其它方法。\n",
    "\n",
    "Tips: 将正则表达式编译为正则对象的好处是方便的进行重复利用，对于相对复杂的正则表达式，无需进行重复编写。\n",
    "\n",
    ">>> pattern = re.compile(\"d\")\n",
    ">>> pattern.search(\"dog\")      # 从默认位置0开始搜索，匹配成功\n",
    "<re.Match object; span=(0, 1), match='d'>\n",
    ">>> pattern.search(\"dog\", 1)   # 从位置1开始搜索，匹配不成功\n",
    ">>> pattern.search(\"dodg\", 1)\n",
    "<_sre.SRE_Match object; span=(2, 3), match='d'>\n",
    ">>> pattern.match(\"dog\")       # 匹配成功\n",
    "<_sre.SRE_Match object; span=(0, 1), match='d'>\n",
    ">>> pattern.match(\"dodg\", 1)   # 从位置1开始搜索，匹配不成功\n",
    "这里的 match 和 search 是正则对象方法，也就是说它们是作用在一个正则对象（由 re.compile(pattern) 返回的），与模块级别的方法 re.match 和 re.search 的使用大致相同：match 也是只关心搜索的开始索引位置是否匹配成功，而 search 从开始索引的位置开始搜索整个字符串并找到第一个匹配成功的位置。但是，注意它们的参数签名是不一样的。\n",
    "\n",
    "re.search(pattern, string, flags=0)\n",
    "re.match(pattern, string, flags=0)\n",
    "Pattern.search(string[, pos[, endpos]])\n",
    "Pattern.match(string[, pos[, endpos]])\n",
    "re.sub\n",
    "通常用来查找并替换一部分字符串以获得新的字符串。\n",
    "\n",
    ">>> input = 'abc   def'\n",
    ">>> re.sub('abc', '', input)     # 用空字符串替换'abc'，这样就间接地移除'abc'\n",
    ">>> re.sub('abc',  'def', input) # 'def'替换'abc'\n",
    ">>> re.sub(r'\\s+',  ' ', input)  # 移除多余的空格\n",
    ">>> re.sub(\"(\\d+) (\\w+)\", r\"\\2 \\1\"， “123 abc”) # 数字引用匹配项然后再进行替换\n",
    ">>> re.sub(\"(?P<number>\\d+) (?P<word>\\w+)\", r\"\\g<word> \\g<number>\", \"123 abc\") # 使用自定义命名组合\n",
    "Tips: 这里要提一个，以上的例子中有的字符串前有 r。r 表示这个字符串是原始字符串，里面的反斜杠不必做任何特殊处理，比如 r'\\n'，它表示两个字符组成，而不是一个换行的字符串。样式（pattern）通常都会使用这种原始字符串表示法来表示。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}